package com.usian.service.lmpl;

import com.usian.game.Game;
import com.usian.mapper.GameMapper;
import com.usian.message.Message;
import com.usian.role.Role;
import com.usian.service.GameService;
import com.usian.user.User;
import com.usian.vo.Result;
import com.usian.vote.Vote;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class GameServicelmpl implements GameService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private GameMapper gameMapper;

    @Override
    public void startGame(Integer roomid) {
        //获取当前房间玩家信息
        List<User> user = redisTemplate.opsForList().range(roomid + "roomUser", 0, -1);
        //打乱
        Collections.shuffle(user);
        //存储打乱房间玩家信息
        List<User> userList = user;
        //获取所有角色
        List<Role> roles = gameMapper.getRole();
        Collections.shuffle(roles);
        //录入游戏信息
        for (int i = 0; i < userList.size(); i++) {
            Game game = new Game();
            game.setRoomId(roomid);
            game.setUserId(userList.get(i).getId());
            game.setRoleId(roles.get(i).getId());
            gameMapper.insertGame(game);
        }
        //将游戏开始时角色录入redis中
        redisTemplate.delete(roomid + "game");
        List<Game> games = gameMapper.getGame(roomid);
        redisTemplate.opsForList().rightPushAll(roomid + "game", games);
        redisTemplate.expire(roomid + "game", 50, TimeUnit.MINUTES);
    }

    @Override
    public List<Game> getGameUser(Integer roomid) {
        List<Game> games = redisTemplate.opsForList().range(roomid + "game", 0, -1);
        Collections.reverse(games);
        if (games.size() <= 0) {
            return null;
        } else {
            return games;
        }
    }

    @Override
    public void sendMessage(Message message) {
        //判断是否为白天
        List<Game> gameList = redisTemplate.opsForList().range(message.getRoomId() + "game", 0, -1);
        if (message.getDayStatus()) {
            for (int i = 0; i < gameList.size(); i++) {
                if (gameList.get(i).getUserId() == message.getSenduserId()){
                    message.setSendName(i+1 + "号玩家");
                    redisTemplate.opsForList().rightPush(message.getRoomId() + "gamemessage", message);
                    redisTemplate.expire(message.getRoomId() + "gamemessage", 50, TimeUnit.MINUTES);
                    return;
                }
            }
            //白天消息正常存入
        } else {
            //黑天狼人消息
            if (message.getRoleId() == 5 || message.getRoleId() == 6) {
                for (int i = 0; i < gameList.size(); i++) {
                    if (gameList.get(i).getUserId() == message.getSenduserId()){
                        message.setSendName(i+1 + "号玩家");
                        redisTemplate.opsForList().rightPush(message.getRoomId() + "werewolfMessage", message);
                        redisTemplate.expire(message.getRoomId() + "werewolfMessage", 50, TimeUnit.MINUTES);
                        return;
                    }
                }
            }
        }
    }

    @Override
    public List<Message> getGameMessage(Integer roomid) {
        return redisTemplate.opsForList().range(roomid + "gamemessage", 0, -1);
    }

    @Override
    public void killUser(Integer roomid, Integer userId, Integer killUserId) {
        // 查询 Redis 中的游戏数据
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
//        Collections.reverse(gameList);
        if (gameList == null) {
            return;
        }
        Game game = new Game();
        //取出gameList对应的索引下标
        if (gameList != null) {
            Game game1 = gameList.get(killUserId);
            //把game1赋值给game
            game = game1;
        }
        if (game == null) {
            return;
        }
        //取出来要杀的人的id
        Integer userId1 = game.getId();
        // 统计狼人数量
        int werewolfCount = 0;

        // 遍历 gameList，判断每个 Game 实例是否是狼人
        if (gameList != null) {
            for (Game game2 : gameList) {
                // 判断狼人是否已经死了
                if (game2.getRoleId() == 5 || game2.getRoleId() == 6) {
                    if (game2.getDeal() != 1) {
                        werewolfCount++;
                    }
                }
            }
        }// 判断如果狼人数量为2
        if (werewolfCount == 2) {
//            先查看队友是否已经选择要杀死的人，如果没有把自己的存入进去
            if (redisTemplate.opsForList().size(roomid + "killUserId") == 0) {
                redisTemplate.opsForList().rightPushAll(roomid + "killUserId", userId1);
                //查找用户对应的角色名称
                String killRoleName = gameMapper.getRoleName(game.getRoleId());
                String causeOfDeath = "狼人杀死" + killRoleName;
                //把当前这个用户的数据存入到数据库记录里面
                gameMapper.addGameLogs(roomid, userId, userId1, "狼人", causeOfDeath, killRoleName);
                return;
            }
            //定义一个队友杀人的变量
            Integer killUserId1 = null;
            if (redisTemplate.opsForList().size(roomid + "killUserId") == 1) {
//                如果队友已经选择了，那么就拿出来
                killUserId1 = (Integer) redisTemplate.opsForList().index(roomid + "killUserId", 0);
            }
            if (killUserId1 != null) {
                if (killUserId1.equals(userId1)) {
                    // 处理杀人逻辑
//                    gameMapper.killUser(roomid, userId, userId1);
                    // 更新Redis
//                    redisTemplate.delete(roomid + "game");
                    redisTemplate.opsForValue().set(roomid + "round", 2);
                    //新添加一条redis，是被杀人的数据
                    List<Game> gameList1 = gameMapper.selectById(game.getId());
                    //把这个数据存入到redis里面
                    redisTemplate.opsForList().rightPushAll(roomid + "death", gameList1);
//                    List<Game> games = gameMapper.getGameUser(roomid);
//                    redisTemplate.opsForList().rightPushAll(roomid + "game", games);
                    //查找用户对应的角色名称
                    String killRoleName = gameMapper.getRoleName(game.getRoleId());
                    String causeOfDeath = "狼人杀死" + killRoleName;
                    //把当前这个用户的数据存入到数据库记录里面
                    gameMapper.addGameLogs(roomid, userId, userId1, "狼人", causeOfDeath, killRoleName);
                } else {
                    // 随机选择杀人逻辑
                    Random random = new Random();
                    int chosenId = random.nextBoolean() ? killUserId1 : userId1;
                    // 杀死逻辑
//                    gameMapper.killUser(roomid, userId, chosenId);

                    // 更新Redis
//                    redisTemplate.delete(roomid + "game");
                    redisTemplate.opsForValue().set(roomid + "round", 2);
                    //新添加一条redis，是被杀人的数据
                    List<Game> gameList1 = gameMapper.selectById(chosenId);
                    //把这个数据存入到redis里面
                    redisTemplate.opsForList().rightPushAll(roomid + "death", gameList1);
                    //查找用户对应的角色名称
//                    List<Game> games = gameMapper.getGameUser(roomid);
//                    redisTemplate.opsForList().rightPushAll(roomid + "game", games);
                    String killRoleName = gameMapper.getRoleName(game.getRoleId());
                    String causeOfDeath = "狼人杀死" + killRoleName;
                    //把当前这个用户的数据存入到数据库记录里面
                    gameMapper.addGameLogs(roomid, userId, userId1, "狼人", causeOfDeath, killRoleName);
                }
            }
        } else if (werewolfCount == 1) {
//            gameMapper.killUser(roomid, userId, userId1);
            // 更新Redis
//            redisTemplate.delete(roomid + "game");
            redisTemplate.opsForValue().set(roomid + "round", 2);
            //新添加一条redis，是被杀人的数据
            List<Game> gameList1 = gameMapper.selectById(game.getId());
            //把这个数据存入到redis里面
            redisTemplate.opsForList().rightPushAll(roomid + "death", gameList1);
            //查找用户对应的角色名称
//            List<Game> games = gameMapper.getGameUser(roomid);
//            redisTemplate.opsForList().rightPushAll(roomid + "game", games);
            String killRoleName = gameMapper.getRoleName(game.getRoleId());
            String causeOfDeath = "狼人杀死" + killRoleName;
            //把当前这个用户的数据存入到数据库记录里面
            gameMapper.addGameLogs(roomid, userId, userId1, "狼人", causeOfDeath, killRoleName);
        }
    }


    @Override
    public String showindex(Integer roomid) {
        Object index = redisTemplate.opsForValue().get(roomid + "round");
        if (index != null) {
            return index.toString();
        } else {
            return null;
        }
    }


    @Override
    public void poisonKill(Integer roomid, Integer index) {
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
//        Collections.reverse(gameList);
        if (gameList == null) {
            return;
        }
        Game game = new Game();
        //取出gameList对应的索引下标
        if (gameList != null) {
            Game game1 = gameList.get(index);
            //把game1赋值给game
            game = game1;
        }
        List<Game> deathList = redisTemplate.opsForList().range(roomid + "death", 0, -1);
        for (Game game1 : deathList) {
            if (game1.getId() == game.getId()){
                return;
            }
        }
        if (game == null) {
            return ;
        }
        List<Game> gameList1 = gameMapper.selectById(game.getId());
        redisTemplate.opsForList().rightPushAll(roomid + "death", gameList1);
    }

    @Override
    public void jump(Integer roomid, Integer userid) {
        redisTemplate.opsForValue().set(roomid + "jump" + userid, 1, 5, TimeUnit.SECONDS);
    }


    @Override
    public Integer getPosion(Integer roomid) {
        return gameMapper.getPosion(roomid);
    }

    @Override
    public List<Message> getGameWerewolfMessage(Integer roomid) {
        return redisTemplate.opsForList().range(roomid + "werewolfMessage", 0, -1);
    }

    //先从redis中获取投票用户，如果为空则将自己的投票结果存入redis中，如果不为空则看长度+1够不够存活人数，如果够就把所有投票用户都取出来，然后判断票数最多的人，将票数最多给一个死亡状态
    @Override
    public void castVote(Integer roomId, int indexUser, int myindex) {
        String voteKey = roomId + "game";
        String voteListKey = roomId + "Vote";
        Message message = new Message();
        message.setSendName("系统");
        message.setRoomId(roomId);
        message.setMessage(myindex+"投票了"+(indexUser+1)+"号玩家");
        redisTemplate.opsForList().rightPush(message.getRoomId() + "gamemessage", message);
        redisTemplate.expire(message.getRoomId() + "gamemessage", 50, TimeUnit.MINUTES);
        // 从 Redis 中获取当前房间玩家游戏数据
        List<Game> gameData = redisTemplate.opsForList().range(voteKey, 0, -1);

        // 使用索引值获取被投票玩家游戏数据
        Game votedPlayer = gameData.get(indexUser);
        redisTemplate.opsForList().rightPushAll(voteListKey, votedPlayer);
        redisTemplate.expire(voteListKey, 120, TimeUnit.SECONDS);
//
//        // 从 Redis 中获取投票用户列表
//        List<Game> voteResults = redisTemplate.opsForList().range(voteListKey, 0, -1);
//
//        if (voteResults == null || voteResults.size()==0) {
//            // 如果投票列表为空，则将自己的投票结果存入 Redis
//            redisTemplate.opsForList().rightPush(voteListKey, votedPlayer);
//        } else {
//            int aliveCount = 0; // 存活人数
//            //获取存活人数
//            for (Game voteResult : gameData) {
//                if (voteResult.getDeal()!=1){
//                    aliveCount++;
//                }
//            }
//            // 检查投票列表长度加 1 是否达到存活人数
//            if (voteResults.size() + 1 >= aliveCount) {
//                // 将自己的投票结果存入 Redis
//                redisTemplate.opsForList().rightPush(voteListKey, votedPlayer);
//
//                List<Game> voteList = redisTemplate.opsForList().range(voteListKey, 0, -1);
//                Map<Integer, Long> voteCounts = voteList.stream()
//                        .collect(Collectors.groupingBy(Game::getId, Collectors.counting()));
//
//                // 找出最大投票数量
//                Optional<Long> maxCountOptional = voteCounts.values().stream().max(Long::compare);
//                if (!maxCountOptional.isPresent()) {
//                    return;
//                }
//                long maxCount = maxCountOptional.get();
//
//                // 找出所有投票数量等于最大投票数量的 ID
//                List<Integer> mostVotedIds = voteCounts.entrySet().stream()
//                        .filter(entry -> entry.getValue() == maxCount)
//                        .map(Map.Entry::getKey)
//                        .collect(Collectors.toList());
//
//                // 如果有多个 ID 的投票数量相同且为最大值，则删除 voteListKey
//                if (mostVotedIds.size() > 1) {
//                    redisTemplate.delete(voteListKey);
//                    return;
//                }
//
//                // 否则，返回投票数量最多的 Game 对象
//                int mostVotedId = mostVotedIds.get(0);
//                //投票玩家最多的人
//                Game mostVotedPlayer = voteList.stream()
//                        .filter(game -> game.getId() == mostVotedId)
//                        .findFirst()
//                        .orElse(null);
//                //将该玩家的信息存入redis中
//                redisTemplate.opsForList().rightPush(voteListKey + "Kill", mostVotedPlayer);
//                // 设置键的过期时间为 3 分钟（180 秒）
//                redisTemplate.expire(voteListKey + "Kill", 180, TimeUnit.SECONDS);
//                //改变该玩家的状态
//                gameMapper.usePoison(roomId,mostVotedPlayer.getId());
//                // 删除 "房间id + game" 的 Redis 数据
//                redisTemplate.delete(voteKey);
//                redisTemplate.delete(voteListKey);
//
//                // 根据房间 ID 查询 game 表获取玩家游戏数据
//                // 这里假设有一个方法来查询数据库并返回玩家数据
//                List<Game> updatedGameData = gameMapper.getGame(roomId);
//
//                // 将更新后的玩家数据存入 Redis
//                redisTemplate.opsForList().leftPushAll(voteKey, updatedGameData);
//            } else {
//                redisTemplate.opsForList().rightPush(voteListKey, votedPlayer);
//            }
//        }
    }

    @Override
    public Integer VoteSelect(Integer roomid) {
        List<Game> gameData = redisTemplate.opsForList().range(roomid + "game", 0, -1);
        //获取投票数据
        List<Game> voteResults = redisTemplate.opsForList().range(roomid + "Vote", 0, -1);
        if (voteResults == null) {
            return null;
        }
        List<Game> voteList = redisTemplate.opsForList().range(roomid + "Vote", 0, -1);
        Map<Integer, Long> voteCounts = voteList.stream()
                .collect(Collectors.groupingBy(Game::getId, Collectors.counting()));

        // 找出最大投票数量
        Optional<Long> maxCountOptional = voteCounts.values().stream().max(Long::compare);
        if (!maxCountOptional.isPresent()) {
            return null;
        }
        long maxCount = maxCountOptional.get();

        // 找出所有投票数量等于最大投票数量的 ID
        List<Integer> mostVotedIds = voteCounts.entrySet().stream()
                .filter(entry -> entry.getValue() == maxCount)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        // 如果有多个 ID 的投票数量相同且为最大值，则删除 voteListKey
        if (mostVotedIds.size() > 1) {
            return null;
        }

        // 否则，返回投票数量最多的 Game 对象
        int mostVotedId = mostVotedIds.get(0);
        //投票玩家最多的人
        Game mostVotedPlayer = voteList.stream()
                .filter(games -> games.getId() == mostVotedId)
                .findFirst()
                .orElse(null);
        gameMapper.usePoison(roomid, mostVotedPlayer.getId());
        int key = 0;
        Game games = new Game();
        for (int i = 0; i < gameData.size(); i++) {
            if (gameData.get(i).getId() == mostVotedPlayer.getId()) {
                key = i;
                games = gameData.get(i);
            }
        }
        games.setDeal(1);
        redisTemplate.opsForList().set(roomid + "game", key, games);
        for (int i = 0; i < gameData.size(); i++) {
            if (gameData.get(i).getId() == mostVotedPlayer.getId()) {
                //返回下标(玩家号)
                return i + 1;
            }
        }
        return null;
    }

    @Override
    public void usePoison(Integer roomid, int id) {
        gameMapper.usePoison(roomid, id);
    }

    @Override
    public void delateWhite(Integer roomid, int id) {
        redisTemplate.delete(roomid + "Vote");
        redisTemplate.delete(roomid + "killUserId");
        redisTemplate.delete(roomid + "VoteSelect");
        // 构建 Redis 中的键
        String key = roomid + "game";

        // 获取 List 中的所有元素
        List<Game> gameList = redisTemplate.opsForList().range(key, 0, -1);

        // 找到 id 对应的元素的索引
        int index = -1;
        for (int i = 0; i < gameList.size(); i++) {
            if (gameList.get(i).getId() == id) {
                index = i;
                break;
            }
        }

        // 如果找到了对应的元素，则更新该元素的 deal 字段
        if (index != -1) {
            // 获取该元素
            Game game = gameList.get(index);
            // 更新 deal 字段
            game.setDeal(1);

            // 更新 Redis 中的元素
            redisTemplate.opsForList().set(key, index, game);

            // 同步更新数据库
            gameMapper.usePoison(roomid, id);
        }
    }

    @Override
    public void hunterkill(Integer roomid, Integer index) {
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
        Game game = new Game();
        //取出gameList对应的索引下标
        if (gameList != null) {
            Game game1 = gameList.get(index);
            //把game1赋值给game
            game = game1;
        }
        gameMapper.usePoison(roomid, game.getId());
        redisTemplate.opsForList().rightPush(roomid + "hunterKill", game);
    }

    @Override
    public Integer hunterKill(Integer roomid) {
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
        List<Game> hunterKillList = redisTemplate.opsForList().range(roomid + "hunterKill", 0, -1);

        // 如果 gameList 为空，则从数据库中获取
        if (gameList.isEmpty()) {
            gameList = gameMapper.getGame(roomid);
        }

        int key = -1; // 初始化为无效值

        // 检查 hunterKillList 是否为空
        if (hunterKillList != null && !hunterKillList.isEmpty()) {
            Game game = hunterKillList.get(0);
            for (int i = 0; i < gameList.size(); i++) {
                if (gameList.get(i).getId() == (game.getId())) {
                    key = i;
                    break;
                }
            }

            if (key != -1) {
                game.setDeal(1);
                redisTemplate.opsForList().set(roomid + "game", key, game);
                return key + 1;
            }
        }

        // 如果 hunterKillList 为空或未找到匹配的游戏，返回 null 或者抛出异常
        return null; // 或者抛出自定义异常
    }


    @Override
    public void BlackDeal(Integer roomid,Integer daynum) {
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
        if (gameList == null) {
            List<Game> gameData = gameMapper.getGame(roomid);
            redisTemplate.opsForList().rightPushAll(roomid + "game", gameData);
        }
        redisTemplate.delete(roomid + "death");
        redisTemplate.delete(roomid + "round");
        redisTemplate.delete(roomid + "hunterKill");
        redisTemplate.delete(roomid + "Vote");
        redisTemplate.delete(roomid + "killUserId");
        redisTemplate.delete(roomid + "VoteSelect");
        redisTemplate.delete(roomid + "NotVote");
    }

    @Override
    public void goodendwin(Integer userid) {
        User user = gameMapper.selectByIdUser(userid);
        user.setAccruedGames(user.getAccruedGames()+1);
        user.setCharisma(user.getCharisma()+60);
        gameMapper.updateByIdUser(user);
    }

    @Override
    public void badendwin(Integer userid) {
        User user = gameMapper.selectByIdUser(userid);
        user.setCharisma(user.getCharisma()+80);
        user.setAccruedGames(user.getAccruedGames()+1);
        gameMapper.updateByIdUser(user);
    }

    @Override
    public void endfail(Integer userId) {
        User user = gameMapper.selectByIdUser(userId);
        user.setCharisma(user.getCharisma()-30);
        user.setAccruedGames(user.getAccruedGames()+1);
        gameMapper.updateByIdUser(user);
    }

    @Override
    public void quitGame(Integer roomid, Integer userid) {
        //获取游戏数据
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
        Message message = new Message();
        for (int i = 0; i < gameList.size(); i++) {
            if (gameList.get(i).getUserId() == userid){
                gameList.get(i).setDeal(1);
                redisTemplate.opsForList().set(roomid + "game", i, gameList.get(i));
                message.setSendName("系统通知:"+(i+1) + "号玩家");
                message.setRoomId(roomid);
                message.setMessage("退出了游戏");
                redisTemplate.opsForList().rightPush(message.getRoomId() + "gamemessage", message);
                redisTemplate.expire(message.getRoomId() + "gamemessage", 50, TimeUnit.MINUTES);
            }
        }
    }

    @Override
    public void voteselect(Integer roomid,Integer index, Integer userid) {
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
        //获取投票方的索引值
        int key = 0;
        for (int i = 0; i <gameList.size() ; i++) {
            if (gameList.get(i).getUserId() == userid){
                key = i+1;
            }
        }
        Vote vote = new Vote();
        vote.setSendIndex(key);
        vote.setVoteIndex(index+1);
        redisTemplate.opsForList().rightPushAll(roomid + "VoteSelect", vote);
    }

    @Override
    public List<Vote> VoteLook(Integer roomid) {
        return redisTemplate.opsForList().range(roomid + "VoteSelect", 0, -1);
    }

    @Override
    public void poisonround(Integer roomid, Integer round) {
        List<Game> killUserIdList = redisTemplate.opsForList().range(roomid + "death", 0, -1);
        if (killUserIdList.size() == 0){
            Integer killUserId1 = null;
            killUserId1 = (Integer) redisTemplate.opsForList().index(roomid + "killUserId", 0);
            if (killUserId1 == null){
                return;
            }
            List<Game> gameList = redisTemplate.opsForList().range(roomid + "game", 0, -1);
            for (int i = 0; i < gameList.size(); i++) {
                if (gameList.get(i).getId() == killUserId1){
                    redisTemplate.opsForList().rightPushAll(roomid + "death",gameList.get(i));
                    return;
                }
            }
        }
    }
    @Override
    public Integer VoteJump(Integer roomid) {
        List<Game> gameList = redisTemplate.opsForList().range(roomid + "Vote", 0, -1);
        List<Game> gameList1 = redisTemplate.opsForList().range(roomid + "NotVote", 0, -1);
        return (gameList.size()+gameList1.size());
    }
}
